﻿using System;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
using System.Text;

namespace SIOsystem.Control
{
    class PrintHelper
    {
        private DataTable DataTable;
        private PrintDocument printDocument;
        private PageSetupDialog pageSetupDialog;
        private PrintPreviewDialog printPreviewDialog;

        private int rowCount = 0;
        private int colCount = 0;
        private int sumIndex = 0;
        private int x = 0;
        private int y = 0;
        int index = 0;
        int[] arrColWidth = null;
        string[] subHeadString = null;
        string[] endString = null;
        string[] midString = null;
        bool fixBigHead = false;
        bool fixHead = true;
        private int headGap = 120;
        private int rowGap = 30;
        private int leftMargin = 40;
        private int HideColCount = 0;
        private Font font = new Font("宋体", 12);
        private Font bigheadFont = new Font("宋体", 20, FontStyle.Bold);
        private Font subbigheadFont = new Font("宋体", 13);
        private Font headingFont = new Font("宋体", 14, FontStyle.Bold);
        private Font sumFont = new Font("宋体", 12, FontStyle.Bold);
        private Brush brush = new SolidBrush(Color.Black);
        private string cellValue = string.Empty;
        private string headString = string.Empty;
        private string keyWordName = string.Empty;


        public PrintHelper(DataTable DataTable)
        {
            this.DataTable = DataTable;
            printDocument = new PrintDocument();
            printDocument.PrintPage += new PrintPageEventHandler(this.printDocument_PrintPage);
        }

        public void SetPrint(string headString, int headGap, int HideColCount,int sumIndex, string[] subHeadString, string[] endString)
        {
            this.headString = headString;
            this.headGap = headGap;
            this.HideColCount = HideColCount;
            this.sumIndex = sumIndex;
            this.subHeadString = subHeadString;
            this.endString = endString;
        }

        public void SetPrint(string keyWordName,string[] midString)
        {
            this.keyWordName = keyWordName;
            this.midString = midString;
        }


        private void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            int tableWidth = 0;
            int sumWidth = 0;
            if (index == 0)
            {
                leftMargin = e.MarginBounds.Left;
                rowCount = DataTable.Rows.Count ;
                colCount = DataTable.Columns.Count - HideColCount;
                arrColWidth = new int[colCount];
                for (int j = 0; j < colCount; j++)
                {
                    arrColWidth[DataTable.Columns[j].Ordinal] = Encoding.GetEncoding(936).GetBytes(DataTable.Columns[j].ColumnName.ToString()).Length;
                }
                for (int j = 0; j < Math.Min(DataTable.Rows.Count, 50); j++)
                {
                    for (int k = 0; k < colCount; k++)
                    {
                        int intTemp = Encoding.GetEncoding(936).GetBytes(DataTable.Rows[j][k].ToString()).Length;
                        if (DataTable.Rows[j][k].GetType().ToString() == "System.DateTime")
                        {
                            intTemp = intTemp - 10;
                        }
                        if (intTemp > arrColWidth[k])
                        {
                            arrColWidth[k] = intTemp;
                        }
                    }
                }
                int sumCount = 0;
                foreach (int w in arrColWidth)
                {
                    tableWidth += w;
                    if (sumIndex > sumCount)
                    {
                        sumWidth = tableWidth;
                    }
                    sumCount++;
                }
            }
            y += e.MarginBounds.Top;
            int l = 20;
            if (index == 0 || fixBigHead)
            {
                int headLength = Encoding.GetEncoding(936).GetBytes(headString).Length;
                //print bighead
                e.Graphics.DrawString(headString, bigheadFont, brush, leftMargin + (tableWidth - headLength+4) * l / 2
                                                                    , y + (headGap - l) / 2);
                y += (headGap - l) / 2 + rowGap;
                //print subhead
                for (int j = 0; j < subHeadString.Length; j += 2)
                {
                    e.Graphics.DrawString(subHeadString[j], subbigheadFont, brush, leftMargin, y + (rowGap - l) / 2);
                    e.Graphics.DrawString(subHeadString[j + 1], subbigheadFont, brush
                        , leftMargin + (sumWidth - 4) * l, y + (rowGap - l) / 2);
                    y += rowGap;
                }
            }
            if (index == 0 || fixHead)
            {
                //print headings
                x = leftMargin;
                for (int j = 0; j < colCount; j++)
                {
                    if (DataTable.Columns[j].ColumnName.Length > 0)
                    {
                        cellValue = DataTable.Columns[j].ColumnName;
                        e.Graphics.DrawRectangle(Pens.Black, x, y, arrColWidth[j] * l, rowGap);
                        e.Graphics.DrawString(cellValue, headingFont, brush, x + arrColWidth[j] * l / 4, y + (rowGap - l) / 2);
                        x += arrColWidth[j] * l;
                    }
                }
            }
            //print all rows 
            double moneySum = 0, smallMoneySum = 0;
            string keyword = "";
            int num = 0;
            for (; index < rowCount; index++)
            {
                y += rowGap;
                x = leftMargin;
                if (keyWordName!="" && DataTable.Rows[index][keyWordName].ToString() != keyword)
                {
                    if (smallMoneySum>0)
                    {
                        e.Graphics.DrawRectangle(Pens.Black, x, y, tableWidth * l, rowGap);
                        e.Graphics.DrawString("小计：", subbigheadFont, brush, leftMargin + arrColWidth[0] * l, y + (rowGap - l) / 2);
                        e.Graphics.DrawString(smallMoneySum.ToString("#0.00#"), headingFont, brush
                            , leftMargin + sumWidth * l + 5, y + (rowGap - l) / 2);
                        smallMoneySum = 0;
                        y += rowGap;
                    }
                    e.Graphics.DrawRectangle(Pens.Black, x, y, tableWidth * l, rowGap);
                    e.Graphics.DrawString(midString[0] + ((DateTime)DataTable.Rows[index][midString[1]]).ToString("yyyy/MM/dd")
                        , subbigheadFont, brush, leftMargin, y + (rowGap - l) / 2);
                    e.Graphics.DrawString(midString[2] + DataTable.Rows[index][midString[3]].ToString(), subbigheadFont, brush
                        , leftMargin + (sumWidth - 4) * l, y + (rowGap - l) / 2);
                    y += rowGap;
                    keyword = DataTable.Rows[index][keyWordName].ToString();
                    num = 0;
                }
                for (int j = 0; j < colCount; j++)
                {
                    if (DataTable.Columns[j].ColumnName.Length > 0) 
                    {
                        e.Graphics.DrawRectangle(Pens.Black, x, y, arrColWidth[j] * l, rowGap);
                        switch (DataTable.Rows[index][j].GetType().ToString().Replace("System.", ""))
                        {
                            case "DateTime":
                                cellValue = ((DateTime)DataTable.Rows[index][j]).ToString("yyyy/MM/dd");
                                break;
                            case "Double"://浮点型
                                cellValue = ((Double)DataTable.Rows[index][j]).ToString("#0.00#");
                                break;
                            case "Single":
                                cellValue = ((Single)DataTable.Rows[index][j]).ToString("#0.00#");
                                break;
                            default:
                                cellValue = DataTable.Rows[index][j].ToString();
                                break;
                        }
                        if (j == 0) { cellValue = (num + 1).ToString(); }
                        int cellLength = Encoding.GetEncoding(936).GetBytes(cellValue).Length;
                        e.Graphics.DrawString(cellValue, font, brush, x + arrColWidth[j] * l / 4, y + (rowGap - l) / 2);
                        x += arrColWidth[j] * l;
                        double money = -1;
                        if (double.TryParse(cellValue,out money) && j == sumIndex)
                        {
                            moneySum += money;
                            smallMoneySum += money;
                        }
                    }
                }
                num++;
            }
            y += rowGap;
            if (smallMoneySum > 0)
            {
                x = leftMargin;
                e.Graphics.DrawRectangle(Pens.Black, x, y, tableWidth * l, rowGap);
                e.Graphics.DrawString("小计：", subbigheadFont, brush, leftMargin + arrColWidth[0] * l, y + (rowGap - l) / 2);
                e.Graphics.DrawString(smallMoneySum.ToString("#0.00#"), headingFont, brush
                    , leftMargin + sumWidth * l + 5, y + (rowGap - l) / 2);
                smallMoneySum = 0;
                y += rowGap;
            }
            if (sumIndex >= 0)
            {
                e.Graphics.DrawString("合计：", subbigheadFont, brush, leftMargin + arrColWidth[0] * l, y + (rowGap - l) / 2);
                e.Graphics.DrawString(moneySum.ToString("#0.00#"), headingFont, brush, leftMargin + sumWidth * l+5, y + (rowGap - l) / 2);
            }
            else
            {
                y -= rowGap;
            }
            if (y >= e.PageBounds.Height - (e.PageBounds.Bottom - e.MarginBounds.Bottom + rowGap))
            {
                // 允許多頁打印
                y = 0;
                e.HasMorePages = true;
                index++;
                return;
            }
            y += rowGap * 3/2;
            for (int j = 0; j < endString.Length; j += 2)
            {
                e.Graphics.DrawString(endString[j], subbigheadFont, brush, leftMargin, y + (rowGap - l) / 2);
                int headLength = Encoding.GetEncoding(936).GetBytes(endString[1]).Length;
                e.Graphics.DrawString(endString[j + 1], subbigheadFont, brush, leftMargin + (sumWidth - 4) * l, y + (rowGap - l) / 2);
                y += rowGap;
            }
            if (y >= e.PageBounds.Height - (e.PageBounds.Bottom - e.MarginBounds.Bottom + rowGap))
            {
                // 允許多頁打印
                y = 0;
                e.HasMorePages = true;
                index++;
                return;
            }
            y += rowGap;
            for (int j = 0; j < colCount; j++)
            {
                e.Graphics.DrawString(" ", font, brush, x, y);
            }
            index = 0;
            e.HasMorePages = false;
        }

        public PrintDocument GetPrintDocument()
        {
            return printDocument;
        }

        public void Print()
        {
            try
            {
                pageSetupDialog = new PageSetupDialog();
                pageSetupDialog.Document = printDocument;
                if (pageSetupDialog.ShowDialog()==DialogResult.OK)
                {
                    printPreviewDialog = new PrintPreviewDialog();
                    printPreviewDialog.Document = printDocument;
                    printPreviewDialog.Height = 600;
                    printPreviewDialog.Width = 800;
                    printPreviewDialog.ShowDialog();
                }
            }
            catch (Exception e)
            {
                throw new Exception("打印错误：" + e.Message);
            }
        }
    }
}
